####
#
# Copyright 2007 B. Chandler Carruth
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
####
#
# ./lib/rcons/tools/c_compiler_target.rb
#
# This file provides a C compiler target specialization.
#
####

require( 'set' )

require( 'rcons/tools/compiler_target' )

module RCons

  # Provides a representation for a C compiler.
  #
  # The compiler class implements a registry system of available compiler
  # classes.  Each implemented class available to RCons must register itself
  # with the class.  Registrations is done by setting a rank, and then
  # registering, as follows:
  #
  #   RANK = 1
  #   CCompilerTarget.register( GccCCompilerTarget )
  #
  # As RCons is building projects, the class representing abstracted compilers,
  # in this case +CCompilerTarget+ is queried for a compiler.  The class
  # +GccCCompiler+, which has been registered, is found and returned to use
  # in the compilation of C source files.
  #
  # At the very least, any child class should implement:
  #
  # - +included_files+
  # - +compile+
  # - +link+
  #
  # An example of a child class:  +GccCCompilerTarget+.
  #
  # Extends +CompilerTarget+.
  class CCompilerTarget < CompilerTarget
    # class variable to store available C compilers
    @@subklass_registry = Set.new()

    # Provides a method to register available compilers to the
    # build process.
    #
    # Inputs:
    # +klass+:: the classname of the compiler to register.
    def CCompilerTarget.register( klass )
      @@subklass_registry << klass
    end

    # Provides a method to determine which compiler to use for a build.
    def CCompilerTarget.best_klass()
      @@subklass_registry.max() do |a,b|
        a::RANK <=> b::RANK
      end
    end


    # Initializes the +CCompilerTarget+ object.  Most of the work is handled
    # by parent classes.
    #
    # Inputs:
    # +build_env+:: an +Environment+.
    # +name+:: the name of the CCompiler.
    # +opts+:: any compiler options.
    def initialize( build_env, name, opts = Hash.new() )
      # handle all the defaults for a target
      super( build_env, File.join( 'c', name ), opts )

    end

    # An abstract method that should be implemented in any child class, to
    # examine a source file and determine any included files.  This method
    # is not called recursively on its returned files, and so should
    # find files included within included files until no new
    # files have been encountered.  Recursion, however, can be used
    # within the method.
    #
    # An example implemented function: !!!link here
    #
    # Inputs:
    #
    # +src_file+:: a path to the source file to examine.
    def included_files( src_file )
      []
    end

    # An abstract method that should be implemented in any child class to
    # provide compilation of the source files associated with a target
    # into an object file.  Any compiler-specific flags or conventions
    # are specified within.
    #
    # An example implemented function: GccCCompilerTarget#compile.
    #
    # Inputs:
    #
    # +target_file+:: the name given to the compiled files.
    # +src_files+:: a list of paths for all source files to be compiled.
    def compile( target_file, *src_files )
      false
    end

    # An abstract method that should be implemented in any child class to
    # link object files into executable code.  Any compiler-specific
    # linkage parameters are specified here.
    #
    # An example implemented function: GccCCompilerTarget#link
    #
    # Inputs:
    #
    # +target_file+:: the name given to the linkd files.
    # +src_files+:: a list of paths for all source files to be linkd.
    def link( target_file, *src_files )
      false
    end

  end
end

